今天的內容為使用者資料的寫入與讀取,會與 day23、day24、day25 有關,程式碼中也亦有註解
首先我們需要與資料庫互動,因此需要先定義資料庫與表,昨天我們有先新建一個資料庫:test_database,那今天我們就在這個 test_database 中新建一張表:user_table,新建方式可參照下圖
新增表中欄位資訊的方式就是按滑鼠右鍵 新建 列,如下圖所示:
先新增三個欄位 id, email, password
設置好了後,表的部分就算是大功告成,接下來就是程式碼的部分
整體的結構如下圖所示:
接下來的內容基本就是程式碼,詳情可參照註解,如果想複製貼上,請修改 import 內的路徑,或者可以考慮代碼連結,不過 go.mod 需要從這裡複製貼上
// go.mod
module it
go 1.19
require (
github.com/gin-gonic/gin v1.8.1
github.com/jinzhu/gorm v1.9.16
github.com/joho/godotenv v1.3.0
)
// main.go
package main
import "it/day26/routers"
func main() {
r := routers.InitRouter()
// 定義在哪個 port 上執行
r.Run(":8080")
}
// .env 隱私資料設定檔
DBUSER="root"
DBPASSWORD="1A2B3c4d"
DBHOST="127.0.0.1"
DBPORT="3306"
DBNAME="test_database"
// router.go 定義路徑
package routers
import (
v1 "it/day26/routers/api/v1"
"github.com/gin-gonic/gin"
)
func InitRouter() *gin.Engine {
r := gin.Default()
// 定義前端打的 api 路徑
r.POST("/v1/register", v1.ApiRegister)
r.POST("/v1/login", v1.ApiLogin)
return r
}
// routers/api/model.go
package api
type User struct {
Email string `json:"email"`
Password string `json:"password"`
}
// api.go
package v1
import (
"net/http"
ctr "it/day26/app/controllers/user"
api "it/day26/routers/api"
"github.com/gin-gonic/gin"
)
// 如果是要給前端的 api,函式只能有一個輸入參
// 註冊使用者
func ApiRegister(c *gin.Context) {
input := api.User{}
c.Bind(&input)
result := ctr.RegisterUser(input.Email, input.Password)
template(c, http.StatusOK, result)
}
// 使用者登入
func ApiLogin(c *gin.Context) {
input := api.User{}
c.Bind(&input)
result := ctr.LoginUser(input.Email, input.Password)
template(c, http.StatusOK, result)
}
// 固定形式的輸出,有利於前端使用
func template(c *gin.Context, code int, data interface{}) {
c.JSON(code, gin.H{
"data": data,
})
}
// const.go
package global
// 寫入資料庫的 表 名稱
const UserTable = "user_table"
// db.go
package database
import (
"fmt"
"log"
"os"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/joho/godotenv/autoload"
)
var db *gorm.DB
// init 為特別的函式,只會在程式初始化時執行一次
func init() {
var err error
db, err = gorm.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
os.Getenv("DBUSER"),
os.Getenv("DBPASSWORD"),
os.Getenv("DBHOST")+":"+os.Getenv("DBPORT"),
os.Getenv("DBNAME")))
fmt.Println(os.Getenv("DBUSER"), ":", os.Getenv("DBPASSWORD"), "@tcp(", os.Getenv("DBHOST")+":"+os.Getenv("DBPORT"), ")/", os.Getenv("DBNAME"))
if err != nil {
log.Println(err)
}
}
func CloseDB() {
defer db.Close()
}
func Get() *gorm.DB {
return db
}
// app/models/user/model.go
package user
type User struct {
Email string `gorm:"email"`
Password string `gorm:"password"`
}
// app/models/user/hamdler.go
package user
import (
"fmt"
"it/day26/database"
"it/day26/global"
)
// 新增資料
func CreateUser(email, password string) error {
user := User{Email: email, Password: password}
err := database.Get().Table(global.UserTable).Create(&user).Error
return err
}
// 從資料庫找有沒有相對應的 email 與 password
func LoginUser(email, password string) error {
user := User{Email: email, Password: password}
err := database.Get().Table(global.UserTable).Where("email = ? and password = ?", email, password).Scan(&user).Error
if err != nil {
fmt.Println(err)
}
return err
}
// app/controllers/user/handler.go
package user
import User "it/day26/app/models/user"
// 註冊使用者
// 這邊可以重複註冊,如果不希望有重複的 email 出現,可在資料庫中設定 email 屬性為 unique
func RegisterUser(email, password string) bool {
err := User.CreateUser(email, password)
return err == nil
}
// 使用者登入
// 如果資料庫中沒有找到對應的使用者帳密,回傳 err = record not found,有找到則 err = nil
func LoginUser(email, password string) bool {
err := User.LoginUser(email, password)
return err == nil
}
新增使用者的結果如下:
使用者登入情形:
正確:
錯誤:
https://github.com/luckyuho/ithome30-golang/tree/main/day26